/*
 * ==================================================
 * 项目开发者：JerryStark
 * 开发者Email：4771007@qq.com
 * 开发者QQ:4771007
 * 开发范围：web，wap，android,ios,osx or win or linux 应用
 * ==================================================
 */
package lottery;

import RTPower.RTdate;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.Map;
import java.util.Set;

/**
 * JSON按规则解析string类
 * <br>仅仅处理对应的规则
 *
 * @author jerry
 */
public class ScanJsonData {

    /**
     * 抓取规则的表配置集合
     * <br>class
     * <br>tag
     * <br>id
     * <br>key
     */
    private JsonObject GetTableConf;

    /**
     * 抓取的行配置集合
     * <br>tag
     * <br>line
     */
    private JsonObject GetRowConf;

    /**
     * 抓取的单元格配置集合
     * <br>tag
     */
    private JsonObject GetCellConf;

    /**
     * 抓取的key的配置集合
     * <br>最终具体抓取的映射
     * <br>orderid
     * <br>numbers
     * <br>number_split_tag
     * <br>time
     * <br>time_format
     */
    private JsonObject GetKeyConf;

    /**
     * 要解析的字符串
     */
    private String ScanString;
    /**
     * 传入的string解析成json 的数据
     */
    private JsonObject JsonData = new JsonObject();

    /**
     * 最终解析完毕的数据
     */
    private JsonObject NewData = new JsonObject();

    /**
     * 接收扫描的字符和规则
     * <br>对规则进行拆分,对字符进行解析json
     *
     * @param scan_string
     * @param ScanRule
     */
    public ScanJsonData(String scan_string, JsonObject ScanRule) {
        ScanString = scan_string;

        //规则进行拆分
        GetTableConf = ScanRule.getAsJsonObject("table_conf");
        GetRowConf = ScanRule.getAsJsonObject("row_conf");
        GetCellConf = ScanRule.getAsJsonObject("cell_conf");
        GetKeyConf = ScanRule.getAsJsonObject("key_conf");
    }

    /**
     * 开始进行正式解析操作
     * <br>最终返回解析完毕的数据
     * <br>不成功就直接是空的对象
     *
     * @return
     */
    public JsonObject Start() {
        ChanageStringToJson();
        //没有解析成功数据就直接终止
        if (JsonData.entrySet().isEmpty()) {
            return NewData;
        }
        //不为空就是解析成功了
        StartScan();

        return NewData;
    }

    /**
     * 解析传入的string为json数据
     */
    private void ChanageStringToJson() {
        //将数据转化为json
        Gson json = new Gson();
        try {
            JsonData = json.fromJson(ScanString, JsonObject.class);
        } catch (Exception e) {
            //解析不成功,直接返回空
            System.err.println("解析字符串失败:" + ScanString);
        }
    }

    /**
     * 开始解析
     */
    private void StartScan() {
        //先解析表
        Object table_data = ScanRuleTable();
        //再解析行
        JsonObject row_data = ScanRuleRow(table_data);
        //再解析cell,row 已经得到了一行数据了,以下就直接进行key对应就可以了
        NewData = ScanRuleKey(row_data);
    }

    /**
     * 先进行表规则的运行,提取表的数据
     * <br>json数据一般使用table conf 的 key 用来定位 数组的key名称
     * <br>如果key为空,就说明是直接就是一个数组
     */
    private Object ScanRuleTable() {
        String table_key = GetTableConf.get("key").getAsString();
        //如果key没有定义则终止,就是直接使用jsondata的数据
        if (table_key.equals("")) {
            return JsonData;
        }

        Object back_json = JsonData.get(table_key);

        //不为空就提取配置的key的值
        return back_json;
    }

    /**
     * 按顺序解析行的规则 最终提取出数据
     *
     * @param table_data
     * @return
     */
    private JsonObject ScanRuleRow(Object table_data) {

        Object row_data = table_data;

        //获得tag
        String row_tag = GetRowConf.get("tag").getAsString();

        //如果定位行tag存在则覆盖掉table
        if (!row_tag.equals("")) {
            row_data = ((JsonObject) table_data).getAsJsonObject(row_tag);
        }

        //如果存在行定位则
        if (GetRowConf.has("line")) {
            if (GetRowConf.get("line").getAsString().equals("")) {
                return (JsonObject) row_data;
            }
            //json的行规则,是读取数组中指定的序列,用到的是line 数字型
            int row_line = GetRowConf.get("line").getAsInt();
            //这里可能是array 或者ob
            if (row_data instanceof JsonObject) {

                JsonObject tdata = (JsonObject) row_data;
                Set<Map.Entry<String, JsonElement>> count = tdata.entrySet();
                for (int i = 0; i < count.size(); i++) {
                    Map.Entry<String, JsonElement> getdata = count.iterator().next();
                    if (i == row_line) {
                        JsonObject new_row_data = new JsonObject();
                        new_row_data = (JsonObject) getdata.getValue();
                        new_row_data.addProperty("key", getdata.getKey());
                        row_data = new_row_data;
                        break;
                    }
                }

            }
            if (row_data instanceof JsonArray) {
                row_data = ((JsonArray) table_data).get(row_line).getAsJsonObject();
            }

        }

        return (JsonObject) row_data;
    }

    /**
     * 键值对应的规则提取数据
     *
     * @param row_data
     * @return
     */
    private JsonObject ScanRuleKey(JsonObject row_data) {
        if (row_data.entrySet().isEmpty()) {
            return new JsonObject();
        }
        //先解析配置
        String orderid_name = GetKeyConf.get("orderid").getAsString();
        String numbers = GetKeyConf.get("numbers").getAsString();
        String number_split_tag = GetKeyConf.get("number_split_tag").getAsString();
        String time = GetKeyConf.get("time").getAsString();
        String time_format = GetKeyConf.get("time_format").getAsString();

        //开始键值对应读取数据
        String use_orderid = row_data.get(orderid_name).getAsString();
        String use_numbers = row_data.get(numbers).getAsString();
        String use_time = row_data.get(time).getAsString();

        //最终准备返回的数据
        JsonObject back_data = new JsonObject();

        //然后再检测格式化问题
        if (!number_split_tag.equals("")) {
            //切分符号不为空则 切割
            String[] sp_numbers = use_numbers.split(number_split_tag);
            use_numbers = new Gson().toJson(sp_numbers);
        }

        if (!time_format.equals("")) {
            use_time = String.valueOf(RTdate.TimeToStemp(use_time, time_format));
        }

        back_data.addProperty("orderid", use_orderid);
        back_data.addProperty("numbers", use_numbers);
        back_data.addProperty("time", use_time);

        return back_data;
    }
}
